﻿using System;
using System.Web.Mvc;
using ControleRepresentante.Data.Catalogs;
using ControleRepresentante.Logic;
using ControleRepresentante.Logic.Models;
using ControleRepresentante.Logic.Repositories;
using ControleRepresentante.UnitTests.Mocks;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using WebSite.Controllers;
using WebSite.Controllers.PrintTemplates;

namespace ControleRepresentante.UnitTests
{
    [TestClass]
    [DeploymentItem("Empty.mdf", "")]
    public abstract class TestScenario
    {
        protected internal const string AdminUsername = "admin";

        protected internal MockRepositoryProvider RepositoryProvider { get; private set; }
        protected internal MockControllerExtensionProvider ControllerExtensionProvider { get; private set; }
        protected internal ISessionConfiguration SessionConfiguration { get; private set; }
        protected internal IAreaOperacaoRegistry AreaOperacaoRegistry { get; private set; }
        protected internal IPrintTemplateSelector PrintTemplateSelector { get; private set; }
        protected internal HtmlHelper HtmlHelper { get; private set; }
        protected internal MockImpostoProvider ImpostProvider { get; private set; }

        [TestInitialize]
        public void TestInitialize()
        {
            Logic.AreaOperacaoRegistry.AddMockArea();
            HtmlHelper = new HtmlHelper(new ViewContext(), new ViewPage());
            AreaOperacaoRegistry areaOperacaoRegistry = new AreaOperacaoRegistry();
            Logic.AreaOperacaoRegistry.RegisterControleRepresentanteAreas(areaOperacaoRegistry);
            areaOperacaoRegistry.Register(Area.Mock, Operacao.Create, Operacao.Delete, Operacao.Update, Operacao.View);
            AreaOperacaoRegistry = areaOperacaoRegistry;

            MockSessionConfiguration mockSessionConfiguration = new MockSessionConfiguration();
            SessionConfiguration = mockSessionConfiguration;

            ImpostProvider = new MockImpostoProvider();

            IRepositoryProviderConfiguration repositoryProviderConfiguration = 
                new MockRepositoryProviderConfigurationSqlite(mockSessionConfiguration);
                //new MockRepositoryProviderConfigurationSqlExpress(mockSessionConfiguration);

            ControllerExtensionProvider = new MockControllerExtensionProvider();
            PrintTemplateSelector = new PrintTemplateSelector();

            RepositoryProvider = new MockRepositoryProvider(repositoryProviderConfiguration);
            RegisterRepositories(RepositoryProvider);

            CreateAdminUser();

            Initialize();
        }

        private void CreateAdminUser()
        {
            IUserRepository userRepository = RepositoryProvider.GetRepository<IUserRepository>();
            Representante representante;
            if (userRepository.GetUser(AdminUsername, AdminUsername, out representante) == null)
            {
                User user = new User {IsAdmin = true, Username = AdminUsername};
                user.SetPasswordFromRawText(AdminUsername);
                userRepository.AddUser(user);
            }
        }

        protected virtual void Initialize()
        {
        }

        [TestCleanup]
        public void TestCleanup()
        {
            this.Logout();
            RepositoryProvider.CloseSession();
            SqLiteInMemoryTestConnectionProvider.ResetConnection();
        }

        protected virtual void RegisterRepositories(RepositoryProvider<ControleRepresentanteCatalog> repositoryProvider)
        {
            Logic.Repositories.RepositoryProvider.RegisterControleRepresentanteRepositories(repositoryProvider);
            repositoryProvider.RegisterRepository<IMockRepositoryForRepresentante, MockRepositoryForRepresentante>();
        }

        protected internal Representante GetCurrentRepresentante()
        {
            return RepositoryProvider.GetRepository<IMockRepositoryForRepresentante>().Representante;
        }
    }

    public class LoginException : Exception
    {
        public LoginException(string message)
            : base(message)
        {
        }
    }
}
